home *** CD-ROM | disk | FTP | other *** search
- ; Source code for TSR, by John J. Newlin, Page 28, Volume 5.5,
- ; Programmer's Journal
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;RAM resident KERNEL driver for main program in expanded memory
- ;Copyright 1987 by John J. Newlin, 4060-228 Rosenda Court, San
- ;Diego, CA 92122
- ;All rights reserved
- ;Assemble with MASM, link with LINK, convert to .COM with EXE2BIN
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;Equates referencing offset addresses in the main program. Addresses
- ;derived from Turbo Pascal main program - see article text.
- activate equ 2D9FH
- demo_main equ 2DA6H
- emm_handle equ 2DAAH
- loaded_in_emm equ 2DA8H
-
- code segment
- assume cs:code
- org 100h
-
- begin:
- jmp initialize ;jump directly to initialization code
-
- demo LABEL DWORD ;label for far call to main prog
- demo_ofs dw 0 ;offset of main prog handler
- demo_seg dw 0 ;segment of main prog
- i16 LABEL DWORD ;label for far call/jump to int 16h
- i16_ofs dw 0 ;offset of original int 16h
- i16_seg dw 0 ;segment of original int 16h
- save_ss dw 0 ;save caller's SS reg
- save_sp dw 0 ;save caller's SP reg
- save_ax dw 0 ;save caller's AX reg
- hotkey db 0 ;hotkey value
- active db 0 ;active flag
- handle dw 0 ;EMM handle
- local_stack dw 20 dup(0) ;local stack area
- stkptr dw 0 ;local SP
-
- save_map: push ax
- push dx
- mov dx,cs:handle ;DX gets our handle
- mov ah,47h ;save mapping context
- int 67h ;call EMM
- pop dx
- pop ax
- ret ;
-
- restore_map:
- push ax
- push dx
- mov dx,cs:handle ;DX gets handle
- mov ah,48h ;to restore mapping context
- int 67h ;call EMM
- pop dx
- pop ax
- ret
-
- map_memory:
- push ax
- push bx
- push cx
- push dx
- mov cx,4 ;will map 4 pages
- do_again: mov dx,cs:handle ;DX gets handle
- mov bx,cx ;BX gets logical page
- mov al,cl ;AL gets physical page
- dec bx ;decrement logical page
- dec al ;decrement physical page
- mov ah,44h ;set up for EMM call
- int 67h ;call EMM
- loop do_again ;do again (3,2,1,0)
- pop ax
- pop bx
- pop cx
- pop dx
- ret ;
-
- run_demo:
- call save_map ;save mapping context
- call map_memory ;map our pages in
- mov cs:active,1 ;set active flag
- mov cs:save_ax,ax ;save AX reg
- cli ;turn off interrupts
- mov cs:save_ss,ss ;save caller's SS reg
- mov cs:save_sp,sp ;save caller's SP reg
- mov ax,cs ;get our CS
- mov ss,ax ;put in SS
- mov ax,offset cs:stkptr ;get offset of local stack
- mov sp,ax ;put in SP
- sub sp,2 ;decrement SP
- sti ;enable interrupts
- push ax ;save
- push bx ; caller's
- push cx ; regs
- push dx ; on
- push di ; our
- push si ; local
- push bp ; stack
- push es ;
- call cs:[demo] ;call our main prog
- pop es ;restore
- pop bp ; caller's
- pop si ; regs
- pop di ; from
- pop dx ; our
- pop cx ; local
- pop bx ; stack
- pop ax ;
- cli ;turn off interrupts
- mov ax,cs:save_ss ;get caller's SS reg
- mov ss,ax ;put in SS
- mov sp,cs:save_sp ;restore caller's SP
- mov ax,cs:save_ax ;restore caller's AX
- sti ;enable interrupts
- mov cs:active,0 ;reset active flag
- call restore_map ;restore mapping context
- ret ;return
-
- int16 proc far ;use far attr for returns
- cmp ah,98h ;regular int 16 request?
- jb keys16 ;yes
-
- n00: cmp ah,9Fh ;request to remove?
- jne l1 ;no
- mov ax,cs:demo_seg ;yes, prepare to remove
- mov es,ax ;ES gets frame segment
- mov ah,45h ;prepare to release EM
- mov dx,cs:handle ;load handle in DX
- int 67h ;call EMM to release
- cli ;turn of interrupts
- push ds ;save DS
- mov ax,cs:i16_seg ;get orginal int 16h seg
- mov ds,ax ;put in DS
- mov dx,cs:i16_ofs ;DX = original int 16h ofs
- mov ax,2516h ;set up to re-install
- int 21h ;call DOS to do it
- pop ds ;restore ds
- mov bx,2Ch ;2Ch in PSP has segment
- mov ax,cs:[bx] ;get mem block segment
- mov es,ax ;put in ES for DOS
- mov ah,49h ;set up to release
- int 21h ;call DOS to release
- mov ax,cs ;our segment
- mov es,ax ;put in ES for DOS
- mov ah,49h ;set up to release
- int 21h ;call DOS to release
- sti ;enable interrupts
- mov ah,4Ch ;set up to teminate
- int 21h ;call DOS to terminate
-
- l1:
- cmp ah,9Bh ;requ for presence flag?
- jne keys16 ;no
- mov ax,0ABCDh ;indicator in AX
- iret ;return to caller
-
- no_action16:
- jmp cs:[i16] ;jmp to original int 16h
-
- keys16:
- cmp cs:active,1 ;is demo active?
- je no_action16 ;yes - depart
- cmp ah,1 ;buffer status req?
- ja no_action16 ;no - depart
- je checkchar ;yes - process
-
- getchar: mov ah,0 ;set up to get a char
- pushf ;to fake int call
- call cs:[i16] ;call original int 16h
- cmp al,0 ;alt key pressed?
- jne exit0 ;no - depart
- cmp ah,cs:hotkey ;our hot key?
- je action1 ;yes - process
- exit0: iret ;no - return to caller
-
- action1:
- call run_demo ;call our main prog
- jmp getchar ;go check key buffer
-
- checkchar:
- mov ah,1 ;set up to check buffer
- pushf ;to fake int call
- call cs:[i16] ;call original int 16h
- pushf ;save flags
- jz exit16 ;no key in buffer - depart
- cmp al,0 ;alt key pressed?
- jne exit16 ;no - depart
- cmp ah,cs:hotkey ;our hot key pressed?
- jne exit16 ;no - depart
- mov ah,0 ;remove key from buffer
- call cs:[i16] ;call original int 16h
- call run_demo ;call our main prog
- jmp checkchar ;go check buffer
-
- exit16:
- popf ;discard flags
- ret 2 ;return to caller
- int16 endp
-
-
- initialize proc
- mov ax,cs ;get code seg value
- mov ds,ax ;set DS to same
- continue: mov ah,9Bh ;set up for int 16 query
- int 16h ;call it
- cmp ax,0ABCDh ;is DEMO loaded?
- jne not_loaded ;no, continue
- mov dx,offset loaded_msg ;yes, it's loaded
- mov ah,9 ;set up to write msg
- int 21h ;write it
- mov ah,4Ch ;terminate
- int 21h
- not_loaded: mov ax,3567h ;set up to get int 67h seg
- int 21h ;call DOS
- mov di,10 ;offset of EMM string
- mov si,offset emm_name ;offset of our string
- mov cx,8 ;8 chars to check
- cld ;set direction flag forward
- repz cmpsb ;compare string
- jz emm_ok ;compare ok?
- mov dx,offset emm_msg ;no
- mov ah,9 ;set up for error msg
- int 21h ;call DOS to write
- mov ah,4Ch ;set up to terminate
- int 21h ;terminate
- emm_ok: mov ah,41h ;set up to get EMM segment
- int 67h ;call EMM
- mov cs:demo_seg,bx ;save it
- mov es,bx ;put it in ES
- mov ax,es:[loaded_in_emm] ;get DEMO flag
- cmp ax,9876h ;is it there?
- je demo_present ;yes
- mov dx,offset not_loaded_msg ;no
- mov ah,9 ;set up for error msg
- int 21h ;call DOS to write
- mov ah,4Ch ;set up to terminate
- int 21h ;terminate
- demo_present: mov al,byte ptr es:[activate] ;get hot key
- mov hotkey,al ;save it
- mov ax,word ptr es:[emm_handle] ;get EMM handle
- mov handle,ax ;save it
- mov ax,word ptr es:[demo_main];get DEMO handler offset
- mov demo_ofs,ax ;save it
-
- mov ax,3516h ;set up to get int16 addr
- int 21h ;call DOS to get it
- mov i16_seg,es ;save segment
- mov i16_ofs,bx ;save offset
- mov ax,2516h ;set up to replace with ours
- mov dx,offset int16 ;offset into DX
- int 21h ;call DOS to install
-
- mov dx,offset sign_on ;sign on msg offset
- mov ah,9 ;set up to write
- int 21h ;call DOS to write
-
- mov dx,offset initialize ;last byte of resident code
- int 27h ;terminate & stay resident
-
- emm_name db 'EMMXXXX0',0
- emm_msg db 'No EMM available - aborting',7,'$'
- loaded_msg db 'KERNEL in memory - aborting',7,'$'
- sign_on db 'KERNEL is loaded and DEMO is operational in EMS','$'
- not_loaded_msg db 'DEMO not in expanded memory',7,'$'
-
- initialize endp
- code ends
- end begin
-